# coding=utf8

from xml.dom import minidom
import xml.sax as sax
import xml.etree.ElementTree as ettree


class Preliminary:

    # dataset = []
    # record = {}

    @staticmethod
    def read_data_by_minidom():
        dataset = []
        record = {}

        def parse_xml(node):
            if node.nodeType != 1:
                return
            if node.tagName in ['name', 'age']:
                record[node.tagName] = node.childNodes[0].data
            if node.tagName == 'comment':
                record[node.tagName] = node.attributes.item(0).value
            if node.tagName == 'student':
                dataset.append(record)
            print(node.tagName, record, dataset)
            for c in node.childNodes:
                parse_xml(c)

        doc = minidom.parse('stu52.xml')
        rootNode = doc.documentElement
        parse_xml(rootNode)
        print(dataset)

    @staticmethod
    def read_data_by_minidom_new():
        dataset = []
        # record = {}

        def parse_xml(node):
            if node.nodeType != 1:
                return
            if node.tagName in ['name', 'age']:
                dataset[-1][node.tagName] = node.childNodes[0].data
            if node.tagName == 'comment':
                dataset[-1][node.tagName] = node.attributes.item(0).value
            if node.tagName == 'student':
                dataset.append({})
            print(node.tagName, dataset)
            for c in node.childNodes:
                parse_xml(c)

        doc = minidom.parse('stu52.xml')
        rootNode = doc.documentElement
        parse_xml(rootNode)
        print(dataset)

    @staticmethod
    def read_data_by_elementtree(xml_filename='stu52.xml'):
        dataset = []
        record = {}

        def parse_xml(node):
            if node.tag in ['name', 'age']:
                record[node.tag] = node.text
            if node.tag == 'comment':
                record[node.tag] = node.attrib['value']
            if node.tag == 'student':
                dataset.append(record)
            for subnode in node:
                parse_xml(subnode)

        etree = ettree.parse(xml_filename)		# 解析XML文件数据，返回ElementTree对象
        root = etree.getroot()			        # 获取根节点（Element对象）
        parse_xml(root)
        print(dataset)

    @staticmethod
    def read_data_by_elementtree_new(xml_filename='stu52.xml'):
        dataset = []
        # record = {}

        def parse_xml(node):
            if node.tag == 'student':
                dataset.append({})
            if node.tag in ['name', 'age']:
                dataset[-1][node.tag] = node.text
            if node.tag == 'comment':
                dataset[-1][node.tag] = node.attrib['value']
            for subnode in node:
                parse_xml(subnode)

        etree = ettree.parse(xml_filename)		# 解析XML文件数据，返回ElementTree对象
        root = etree.getroot()			        # 获取根节点（Element对象）
        parse_xml(root)
        print(dataset)

    @staticmethod
    def read_xml_by_minidom():

        def parse_xml_by_minidom(node, level):
            # 非元素节点不解析
            if node.nodeType != 1:
                return

            # 打印每个节点信息的缩进数
            tabstr = "\t"*level
            print("{}--- level: {} ---".format(tabstr, level))

            # 打印该节点的标签名称、数据、属性
            print("{}tagname: {}".format(tabstr, node.tagName))
            if node.tagName in ['name', 'age']:
                print("{}tagdata: {}".format(tabstr, node.childNodes[0].data))
            if node.tagName == 'comment':
                print("{}tagattrib: {}".format(tabstr, node.attributes.item(0).value))

            # 递归该节点的子节点
            for c in node.childNodes:
                # # 文本类节点不递归
                # if c.nodeName != '#text':
                parse_xml_by_minidom(c, level+1)

        doc = minidom.parse('stu52.xml')
        rootNode = doc.documentElement
        parse_xml_by_minidom(rootNode, 0)

    @staticmethod
    def read_xml_by_elementtree(xml_filename='stu52.xml'):

        def parse_xml_by_elementtree(node, level):
            tabstr = "\t"*level
            print("{}--- level: {} ---".format(tabstr, level))
            print("{}tagname: {}".format(tabstr, node.tag))
            if node.text:
                _text = node.text.replace('\n', '').replace(' ', '')
                if len(_text) > 0:
                    print("{}attrib: {}".format(tabstr, node.text))
            if len(node) > 0:
                print("{}subnode: {}".format(tabstr, [subnode.tag for subnode in node]))
            for subnode in node:
                 parse_xml_by_elementtree(subnode, level+1)

        etree = ettree.parse(xml_filename)		# 解析XML文件数据，返回ElementTree对象
        root = etree.getroot()			        # 获取根节点（Element对象）
        parse_xml_by_elementtree(root, 0)

    @staticmethod
    def read_data_by_sax():

        class StudentXMLHandler(sax.ContentHandler):

            def __init__(self):
                super().__init__()
                self.current_tag = ''
                self.record = {"name": '', "age": "", "comment": ""}
                self.records = []

            def startDocument(self):
                """文档解析开始"""
                self.records = []

            def startElement(self, tag, attr):
                """遇到元素开始标签"""
                self.current_tag = tag
                if tag == 'comment':
                    self.record[tag] = attr['value']

            def characters(self, content):
                """
                遇到一个标签或行结束符，返回获取的标签之前内容:
                1. 从一行开始，到一个标签，存在的所有字符。有些可能是空格、回车符等。
                2. 从上一个标签开始，到本标签之间存在的字符。
                3. 从上一个标签开始，到行结束符之前的所有字符。
                """
                # if len(content.strip()) > 0:
                #     print(content)
                if self.current_tag in ['name', 'age']:
                    self.record[self.current_tag] = content

            def endElement(self, tag):
                """遇到元素结束标签"""
                self.current_tag = ''
                if tag == 'student':
                    self.records.append(self.record)
                    self.record = {}

            def endDocument(self):
                """文档解析结束"""
                # print(self.records)

        # 创建解析器
        parser = sax.make_parser()
        # 关闭命名空间(sax不能解析命名空间)
        parser.setFeature(sax.handler.feature_namespaces, 0)
        # 创建、调用回调函数类实例
        handler = StudentXMLHandler()
        parser.setContentHandler(handler)
        # 解析XML文件数据
        parser.parse("stu52.xml")
        print(handler.records)


def task():
    etree = ettree.parse('stu52.xml')
    root = etree.getroot()
    # 搜索root的子节点（各student节点）
    for node in root:
        # 收集student节点的子节点数据
        studict = {subnode.tag: subnode.text for subnode in node}
        if int(studict['age']) > 20:
            print(studict['name'], studict['age'])


def expand_train():

    class StudentXMLHandler(sax.ContentHandler):

        def __init__(self):
            super().__init__()
            self.current_tag = ''
            self.record = {"name": '', "age": "", "comment": ""}
            self.records = []

        def startDocument(self):
            """文档解析开始"""
            self.records = []

        def startElement(self, tag, attr):
            """遇到元素开始标签"""
            self.current_tag = tag
            if tag == 'comment':
                self.record[tag] = attr['value']

        def characters(self, content):
            """
            遇到一个标签或行结束符，返回获取的标签之前内容:
            1. 从一行开始，到一个标签，存在的所有字符。有些可能是空格、回车符等。
            2. 从上一个标签开始，到本标签之间存在的字符。
            3. 从上一个标签开始，到行结束符之前的所有字符。
            """
            # if len(content.strip()) > 0:
            #     print(content)
            if self.current_tag in ['name', 'age']:
                self.record[self.current_tag] = content

        def endElement(self, tag):
            """遇到元素结束标签"""
            self.current_tag = ''
            if tag == 'student':
                if self.record['name'][0] == '李':
                    self.records.append(self.record)
                self.record = {}

        def endDocument(self):
            """文档解析结束"""
            # print(self.records)

    # 创建解析器
    parser = sax.make_parser()
    # 关闭命名空间(sax不能解析命名空间)
    parser.setFeature(sax.handler.feature_namespaces, 0)
    # 创建、调用回调函数类实例
    handler = StudentXMLHandler()
    parser.setContentHandler(handler)
    # 解析XML文件数据
    parser.parse("stu52.xml")
    print(handler.records)


if __name__ == '__main__':
    Preliminary.read_data_by_minidom_new()
    # Preliminary.read_data_by_elementtree()
    # Preliminary.read_data_by_sax()

    # Preliminary.read_xml_by_minidom()
    # Preliminary.read_xml_by_elementtree()

    # task()
    # expand_train()

